#include "server_conn.h"

#include <iostream>

using namespace std;

ServerConn::ServerConn(asio::io_service& ioservice_, UdpService& udpservice, server_options opt_)
: BaseConn(ioservice_, udpservice)
, opt(opt_)
{
}

void ServerConn::handleUdpAccept()
{
	cout << "Handling udp accept, from: " << udpconn.remote_endpoint() << endl;

	// simple header saying we support only version 0
	sendbuf[0] = 0x00;
	sendbuf[1] = 0x01;
	sendbuf[2] = 0x00;
	sendbuf[3] = 0x00;

	asio::async_write(udpconn, asio::buffer(sendbuf, 4),
		boost::bind(&ServerConn::handleSendHeader, this, token, boost::asio::placeholders::error)
	);
}

void ServerConn::handleSendHeader(Token tk, const boost::system::error_code& e)
{
	if (e) {
		cerr << "Failed to send header: " << e.message() << endl;
		close();
		return;
	}

	asio::async_read(udpconn, boost::asio::buffer(recvbuf, 2),
		boost::bind(&ServerConn::handleReadHeader, this, token, boost::asio::placeholders::error)
	);
}


void ServerConn::handleReadHeader(Token tk, const boost::system::error_code& e)
{
	if (e) {
		cerr << "Failed to recieve header: " << e.message() << endl;
		close();
		return;
	}

	uint32 header =
		(recvbuf[0] <<  8) |
		(recvbuf[1] <<  0);

	if (header != 0) {
		cerr << "Unknown header (" << header << ")" << endl;
		close();
		return;
	}

	tcpconn.open(opt.tcp_forward_addr.protocol());
	tcpconn.async_connect(opt.tcp_forward_addr,
		boost::bind(&ServerConn::handleTcpConnect, this, token, boost::asio::placeholders::error)
	);
}

void ServerConn::handleTcpConnect(Token tk, const boost::system::error_code& e)
{
	if (e) {
		cerr << "Failed to connect to tcp (" << opt.tcp_forward_addr << "): " << e.message() << endl;
		close();
		return;
	}

	startForwarding();
}
